﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Addins.UI.ViewModel;
using Raona.Code.Inspection;
using WcfClientGenerator.Model.Common;
using WcfClientGenerator.Model.Config;
using WcfClientGenerator.Model.EventArguments;
using WcfClientGenerator.UI.Command;
using WcfClientGenerator.UI.Resx;
using WcfClientGenerator.UI.UserControls;
using WcfClientGenerator.UI.Util;

namespace WcfClientGenerator.UI.ViewModel
{
    public class EditConfigurationsViewModel : BaseViewModel, IRequestCloseViewModel
    {
        #region Instance Events (Public)

        public event EventHandler RequestClose;
        public event EventHandler<WcfClientGeneratorConfigEventArgs> ConfigurationChanged = null;

        #endregion

        #region Instance Fields (Private)

        #region Attributes

        /// <summary>
        /// The Addin configuration
        /// </summary>
        private WcfClientGeneratorConfig configuration = null;

        /// <summary>
        /// The collection of client configurations
        /// </summary>
        private ObservableCollection<WcfClientConfiguration> clientConfigurations = null;

        /// <summary>
        /// The client configuration being edited
        /// </summary>
        private int currentConfiguration = -1;

        /// <summary>
        /// The confirmation message box to show to the user
        /// </summary>
        private UserControl messageBox = null;

        /// <summary>
        /// The confirmation message to show to the user
        /// </summary>
        private string message = null;

        /// <summary>
        /// The selected client configuration
        /// </summary>
        private WcfClientConfiguration selectedConfiguration = null;

        /// <summary>
        /// The solution object
        /// </summary>
        private EnvDTE80.DTE2 applicationObject = null;

        /// <summary>
        /// The collection of projects selected by the user in the current project selector
        /// </summary>
        private List<SelectedProject> selectedProjects = null;

        /// <summary>
        /// The collection of async proxies target projects selected by the user 
        /// </summary>
        private List<SelectedProject> selectedAsyncProjects = null;

        /// <summary>
        /// The collection of sync proxies target projects selected by the user 
        /// </summary>
        private List<SelectedProject> selectedSyncProjects = null;

        /// <summary>
        /// The control that allows the selection of projects
        /// </summary>
        private UserControl projectSelectionView = null;

        /// <summary>
        /// The list of projects in the current solution
        /// </summary>
        private List<string> solutionProjects = new List<string>();

        private bool isAdvancedView = false;

        #endregion // Attributes

        #region Commands

        /// <summary>
        /// The command to invoke when a new client configuration should be added
        /// </summary>
        private DelegatingCommand addConfigurationCommand = null;

        /// <summary>
        /// The command to invoke when a asking for deletion of a client configuration
        /// </summary>
        private DelegatingCommand confirmDeleteConfigurationCommand = null;

        /// <summary>
        /// The command to invoke when a new client configuration should be deleted
        /// </summary>
        private DelegatingCommand deleteConfigurationCommand = null;

        /// <summary>
        /// The command to invoke when a new client configuration should be created from the current configuration
        /// </summary>
        private DelegatingCommand copyConfigurationCommand = null;

        /// <summary>
        /// The command to invoke when a new destination project for asynchronous proxies should be selected
        /// </summary>
        private DelegatingCommand selectAsyncProxiesDestinationsCommand = null;

        /// <summary>
        /// The command to invoke when a new destination project for synchronous proxies should be selected
        /// </summary>
        private DelegatingCommand selectSyncProxiesDestinationsCommand = null;

        /// <summary>
        /// The command to invoke when the generation folder should be selected
        /// </summary>
        private DelegatingCommand selectGenerationFolderCommand = null;

        /// <summary>
        /// The command invoked when the user accepts the changes made
        /// </summary>
        private DelegatingCommand acceptChangesCommand = null;

        /// <summary>
        /// The command invoked when the user refuses the changes made
        /// </summary>
        private DelegatingCommand ignoreChangesCommand = null;

        /// <summary>
        /// The command invoked when the user accepts in a confirmation message box
        /// </summary>
        private DelegatingCommand confirmCommand = null;

        /// <summary>
        /// The command invoked when the user cancels a confirmation message box
        /// </summary>
        private DelegatingCommand cancelCommand = null;

        /// <summary>
        /// The command invoked for selecting the async proxies destination projects
        /// </summary>
        private DelegatingCommand selectSyncProxiesProjectsCommand = null;

        /// <summary>
        /// Contains the the command to invoke on user confirmation when a project selection action is in process
        /// </summary>
        private DelegatingCommand confirmProjectSelectionCommand = null;

        /// <summary>
        /// Contains the the command to invoke on user cancellation when a project selection action is in process
        /// </summary>
        private DelegatingCommand cancelProjectSelectionCommand = null;

        /// <summary>
        /// The command to invoke when the project selector is used to edit the async proxies destination projects
        /// </summary>
        private DelegatingCommand confirmAsyncProjectsSelectionCommand = null;

        /// <summary>
        /// The command to invoke when the project selector is used to edit the sync proxies destination projects
        /// </summary>
        private DelegatingCommand confirmSyncProjectsSelectionCommand = null;

        /// <summary>
        /// The command to invoke when the templates assembly should be selected
        /// </summary>
        private DelegatingCommand selectTemplatesAssemblyCommand = null;

        /// <summary>
        /// The command to invoke when the selected client configuration should be copied to the clipboard
        /// </summary>
        private DelegatingCommand copySelectedConfigurationToClipboardCommand = null;

        /// <summary>
        /// The command to invoke when a new client configuration should be created from the text in the clipboard
        /// </summary>
        private DelegatingCommand addConfigurationFromClipboardCommand = null;

        /// <summary>
        /// The command to invoke when the selected client configuration should be sent in a e-mail
        /// </summary>
        private DelegatingCommand eMailSelectedConfigurationCommand = null;

        /// <summary>
        /// The command to toggle between the basic and advanced configuration views
        /// </summary>
        private DelegatingCommand toggleViewCommand = null;

        /// <summary>
        /// The command invoked to select the image file to show in the configuration tile 
        /// </summary>
        private DelegatingCommand selectTileImageCommand = null;

        #endregion // Commands

        #endregion

        #region Instance Constructors (Public)

        /// <summary>
        /// Initializing constructor
        /// </summary>
        /// <param name="configuration">The addin configuration object</param>
        /// <param name="applicationObject">The solution object</param>
        public EditConfigurationsViewModel(WcfClientGeneratorConfig configuration, EnvDTE80.DTE2 applicationObject)
        {
            // Edit a copy of the specified configuration
            string xml = SerializationManager.XmlSerializeString(configuration);
            this.configuration = (WcfClientGeneratorConfig)SerializationManager.XmlDeserializeString(xml, typeof(WcfClientGeneratorConfig));
            this.clientConfigurations = new ObservableCollection<WcfClientConfiguration>(this.configuration.ClientConfigurations);
            this.currentConfiguration = this.configuration.CurrentConfiguration;
            if (this.currentConfiguration >= 0 && this.currentConfiguration < this.clientConfigurations.Count)
                this.SelectedConfiguration = this.clientConfigurations[this.currentConfiguration];

            this.applicationObject = applicationObject;
            this.CreateSolutionProjectCollection();
        }

        #endregion

        #region Instance Properties (Public)

        #region Data Bindings

        /// <summary>
        /// The collection of client configurations
        /// </summary>
        public ObservableCollection<WcfClientConfiguration> ClientConfigurations
        {
            get
            {
                return this.clientConfigurations;
            }
        }

        /// <summary>
        /// The currently selected configuration index
        /// </summary>
        public int CurrentConfiguration
        {
            get
            {
                return this.currentConfiguration;
            }
            set
            {
                int oldValue = this.currentConfiguration;
                this.currentConfiguration = value;
                if (this.currentConfiguration != oldValue)
                    this.NotifyPropertyChanged("CurrentConfiguration");
            }
        }

        /// <summary>
        /// The currently selected configuration
        /// </summary>
        public WcfClientConfiguration SelectedConfiguration
        {
            get
            {
                return this.selectedConfiguration;
            }
            set
            {
                WcfClientConfiguration oldConfiguration = this.selectedConfiguration;
                this.selectedConfiguration = value;
                if (this.selectedConfiguration != oldConfiguration)
                    this.NotifyPropertyChanged("SelectedConfiguration");
            }
        }

        /// <summary>
        /// The confirmation message box to show to the user
        /// </summary>
        public UserControl MessageBox
        {
            get
            {
                return this.messageBox;
            }
            set
            {
                this.messageBox = value;
                this.NotifyPropertyChanged("MessageBox");
            }
        }

        /// <summary>
        /// The confirmation message to show to the user
        /// </summary>
        public string Message
        {
            get
            {
                return this.message;
            }
            set
            {
                this.message = value;
                this.NotifyPropertyChanged("Message");
            }
        }

        /// <summary>
        /// The collection of projects selected by the user in the current project selector
        /// </summary>
        public List<SelectedProject> SelectedProjects
        {
            get
            {
                return this.selectedProjects;
            }
            set
            {
                List<SelectedProject> oldProjects = this.selectedProjects;
                this.selectedProjects = value;
                if (oldProjects != this.selectedProjects)
                    this.NotifyPropertyChanged("SelectedProjects");
            }
        }

        /// <summary>
        /// The collection of async proxies target projects selected by the user 
        /// </summary>
        public List<SelectedProject> SelectedAsyncProjects
        {
            get
            {
                return this.selectedAsyncProjects;
            }
            set
            {
                this.selectedAsyncProjects = value;
            }
        }

        /// <summary>
        /// The collection of sync proxies target projects selected by the user 
        /// </summary>
        public List<SelectedProject> SelectedSyncProjects
        {
            get
            {
                return this.selectedSyncProjects;
            }
            set
            {
                this.selectedSyncProjects = value;
            }
        }

        /// <summary>
        /// The control that allows the selection of projects
        /// </summary>
        public UserControl ProjectSelector
        {
            get
            {
                return this.projectSelectionView;
            }
            set
            {
                this.projectSelectionView = value;
                this.NotifyPropertyChanged("ProjectSelector");
            }
        }

        /// <summary>
        /// The collection of project names
        /// </summary>
        public List<string> SolutionProjects
        {
            get
            {
                return this.solutionProjects;
            }
        }

        public override bool CanCopyPasteConfigurations
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Indicates the which view should be shown
        /// </summary>
        public bool IsAdvancedView
        {
            get
            {
                return this.isAdvancedView;
            }
            set
            {
                this.isAdvancedView = value;
                this.NotifyPropertyChanged("IsAdvancedView");
            }
        }

        /// <summary>
        /// The list of colors available as tile backgrounds
        /// </summary>
        public IEnumerable<Brush> TileBrushes
        {
            get
            {
                return TileBackground.Brushes;
            }
        }

        #endregion // Data Bindings

        #region Commands

        /// <summary>
        /// The command to invoke when a new client configuration should be added
        /// </summary>
        public ICommand AddConfigurationCommand
        {
            get
            {
                if (this.addConfigurationCommand == null)
                {
                    this.addConfigurationCommand = new DelegatingCommand(
                        () =>
                        {
                            string name = this.GetNewClientConfigurationName();
                            WcfClientConfiguration clientConfiguration = new WcfClientConfiguration 
                            { 
                                Name = name, 
                                ClientBaseName = "System.ServiceModel.ClientBase",
                                GenerationFolder = System.IO.Path.GetTempPath()
                            };
                            this.clientConfigurations.Add(clientConfiguration);
                            this.SelectedConfiguration = clientConfiguration;
                        },
                        () =>
                        {
                            return true;
                        });
                }
                return this.addConfigurationCommand;
            }
        }

        /// <summary>
        /// The command to invoke when the a new client configuration should be created from the text in the clipboard
        /// </summary>
        public ICommand AddConfigurationFromClipboardCommand
        {
            get
            {
                if (this.addConfigurationFromClipboardCommand == null)
                {
                    this.addConfigurationFromClipboardCommand = new DelegatingCommand(
                        () =>
                        {
                            if (Clipboard.ContainsText(TextDataFormat.Text))
                            {
                                WcfClientConfiguration clientConfiguration = null;
                                try
                                {
                                    clientConfiguration = WcfClientConfiguration.FromString(Clipboard.GetText(TextDataFormat.Text));
                                }
                                finally
                                {
                                }
                                if (clientConfiguration != null)
                                {
                                    this.clientConfigurations.Add(clientConfiguration);
                                    this.SelectedConfiguration = clientConfiguration;
                                }
                            }
                        },
                        () =>
                        {
                            bool canExecute = false;
                            if (Clipboard.ContainsText(TextDataFormat.Text))
                            {
                                WcfClientConfiguration clientConfiguration = null;
                                try
                                {
                                    clientConfiguration = WcfClientConfiguration.FromString(Clipboard.GetText(TextDataFormat.Text));
                                    canExecute = clientConfiguration != null;
                                }
                                finally
                                {
                                }
                            }
                            return canExecute;
                        });
                }
                return this.addConfigurationFromClipboardCommand;
            }
        }

        /// <summary>
        /// The command to invoke when a copy of the selected configuration should be added
        /// </summary>
        public ICommand CopyConfigurationCommand
        {
            get
            {
                if (this.copyConfigurationCommand == null)
                {
                    this.copyConfigurationCommand = new DelegatingCommand(
                        () =>
                        {
                            if (this.SelectedConfiguration != null)
                            {
                                string name = this.GetNewClientConfigurationName();
                                string serializedConfiguration = SerializationManager.XmlSerializeString(this.SelectedConfiguration);
                                WcfClientConfiguration clientConfiguration = SerializationManager.XmlDeserializeString(serializedConfiguration, typeof(WcfClientConfiguration)) as WcfClientConfiguration;
                                clientConfiguration.Name = name;
                                this.clientConfigurations.Add(clientConfiguration);
                                this.SelectedConfiguration = clientConfiguration;
                            }
                        },
                        () =>
                        {
                            return this.SelectedConfiguration != null;
                        });
                }
                return this.copyConfigurationCommand;
            }
        }

        /// <summary>
        /// The command to invoke when the selected client configuration should be copied to the clipboard
        /// </summary>
        public ICommand CopySelectedConfigurationToClipboardCommand
        {
            get
            {
                if (this.copySelectedConfigurationToClipboardCommand == null)
                {
                    this.copySelectedConfigurationToClipboardCommand = new DelegatingCommand(
                        () =>
                        {
                            if (this.SelectedConfiguration != null)
                            {
                                string xml = this.SelectedConfiguration.ToString();
                                Clipboard.SetData(DataFormats.Text, xml);
                            }
                        },
                        () =>
                        {
                            return this.SelectedConfiguration != null;
                        });
                }
                return this.copySelectedConfigurationToClipboardCommand;
            }
        }

        /// <summary>
        /// The command to invoke when the selected client configuration should be sent in a e-mail
        /// </summary>
        public ICommand EMailSelectedConfigurationCommand
        {
            get
            {
                if (this.eMailSelectedConfigurationCommand == null)
                {
                    this.eMailSelectedConfigurationCommand = new DelegatingCommand(
                        () =>
                        {
                            if (this.SelectedConfiguration != null)
                            {
                                string xml = this.SelectedConfiguration.ToString();
                                xml = System.Web.HttpUtility.UrlEncode(xml);
                                xml = xml.Replace('+', ' ');
                                string commandLine = string.Format("mailto:{0}?subject={1}&body={2}", "", this.SelectedConfiguration.Name, xml);
                                Process.Start(commandLine);
                            }
                        },
                        () =>
                        {
                            return this.SelectedConfiguration != null;
                        });
                }
                return this.eMailSelectedConfigurationCommand;
            }
        }

        /// <summary>
        /// The command to invoke when a asking for deletion of a client configuration
        /// </summary>
        public ICommand ConfirmDeleteConfigurationCommand
        {
            get
            {
                if (this.confirmDeleteConfigurationCommand == null)
                {
                    this.confirmDeleteConfigurationCommand = new DelegatingCommand(
                        () =>
                        {
                            this.Message = AppResources.confirmDeleteMessage;
                            this.ConfirmCommand = this.DeleteConfigurationCommand;
                            this.MessageBox = new MessageView { DataContext = this };
                        },
                        () =>
                        {
                            return this.clientConfigurations.Count > 0;
                        });
                }
                return this.confirmDeleteConfigurationCommand;
            }
        }

        /// <summary>
        /// The command to invoke when a new client configuration should be deleted
        /// </summary>
        public ICommand DeleteConfigurationCommand
        {
            get
            {
                if (this.deleteConfigurationCommand == null)
                {
                    this.deleteConfigurationCommand = new DelegatingCommand(
                        () =>
                        {
                            if (this.SelectedConfiguration != null)
                            {
                                this.clientConfigurations.Remove(this.SelectedConfiguration);
                                if (this.clientConfigurations.Count > 0)
                                    this.SelectedConfiguration = this.clientConfigurations[0];
                            }
                            this.MessageBox = null;
                        },
                        () =>
                        {
                            return this.clientConfigurations.Count > 0;
                        });
                }
                return this.deleteConfigurationCommand;
            }
        }

        /// <summary>
        /// The command invoked when the user accepts in a confirmation message box
        /// </summary>
        public ICommand ConfirmCommand
        {
            get
            {
                return this.confirmCommand;
            }
            set
            {
                ICommand oldCommand = this.confirmCommand;
                this.confirmCommand = value as DelegatingCommand;
                if (this.confirmCommand != oldCommand)
                    this.NotifyPropertyChanged("ConfirmCommand");
            }
        }

        /// <summary>
        /// The command invoked when the user cancels a confirmation message box
        /// </summary>
        public ICommand CancelCommand
        {
            get
            {
                if (this.cancelCommand == null)
                {
                    this.cancelCommand = new DelegatingCommand(
                        () =>
                        {
                            this.MessageBox = null;
                        },
                        () =>
                        {
                            return this.MessageBox != null;
                        });
                }
                return this.cancelCommand;
            }
        }

        /// <summary>
        /// The command invoked when the user accepts the changes made
        /// </summary>
        public ICommand AcceptChangesCommand
        {
            get
            {
                if (this.acceptChangesCommand == null)
                {
                    this.acceptChangesCommand = new DelegatingCommand(
                        () =>
                        {
                            this.AcceptConfigurationChanges();
                            this.Close();
                        },
                        () =>
                        {
                            return true;
                        });
                }
                return this.acceptChangesCommand;
            }
        }

        /// <summary>
        /// The command invoked when the user refuses the changes made
        /// </summary>
        public ICommand IgnoreChangesCommand
        {
            get
            {
                if (this.ignoreChangesCommand == null)
                {
                    this.ignoreChangesCommand = new DelegatingCommand(
                       () =>
                       {
                           this.Close();
                       },
                       () =>
                       {
                           return true;
                       });
                }
                return this.ignoreChangesCommand;
            }
        }

        /// <summary>
        /// The command invoked for selecting the async proxies destination projects
        /// </summary>
        public ICommand SelectAsyncProxiesProjectsCommand
        {
            get
            {
                if (this.selectAsyncProxiesDestinationsCommand == null)
                {
                    this.selectAsyncProxiesDestinationsCommand = new DelegatingCommand(
                        () =>
                        {
                            this.SelectedAsyncProjects = this.CreateSelectedProjects(this.SelectedConfiguration.AsyncDestinationProjects);
                            this.SelectedProjects = this.SelectedAsyncProjects;
                            this.ProjectSelector = new ProjectSelectionView();
                            this.ConfirmProjectSelectionCommand = this.ConfirmAsyncProjectsSelectionCommand;
                        },
                        () =>
                        {
                            return this.SelectedConfiguration != null;
                        });
                }
                return this.selectAsyncProxiesDestinationsCommand;
            }
        }

        /// <summary>
        /// The command invoked for selecting the sync proxies destination projects
        /// </summary>
        public ICommand SelectSyncProxiesDestinationsCommand
        {
            get
            {
                if (this.selectSyncProxiesDestinationsCommand == null)
                {
                    this.selectSyncProxiesDestinationsCommand = new DelegatingCommand(
                        () =>
                        {
                            this.SelectedSyncProjects = this.CreateSelectedProjects(this.SelectedConfiguration.SyncDestinationProjects);
                            this.SelectedProjects = this.SelectedSyncProjects;
                            this.ProjectSelector = new ProjectSelectionView();
                            this.ConfirmProjectSelectionCommand = this.ConfirmSyncProjectsSelectionCommand;
                        },
                        () =>
                        {
                            return this.SelectedConfiguration != null;
                        });
                }
                return this.selectSyncProxiesDestinationsCommand;
            }
        }

        /// <summary>
        /// The command invoked when the user confirms the changes in the project selection view
        /// </summary>
        public ICommand ConfirmProjectSelectionCommand
        {
            get
            {
                return this.confirmProjectSelectionCommand;
            }
            set
            {
                ICommand oldCommand = this.confirmProjectSelectionCommand;
                this.confirmProjectSelectionCommand = value as DelegatingCommand;
                if (oldCommand != this.confirmProjectSelectionCommand)
                    this.NotifyPropertyChanged("ConfirmProjectSelectionCommand");
            }
        }

        /// <summary>
        /// The command invoked when the user cancels the changes in the project selection view
        /// </summary>
        public ICommand CancelProjectSelectionCommand
        {
            get
            {
                if (this.cancelProjectSelectionCommand == null)
                {
                    this.cancelProjectSelectionCommand = new DelegatingCommand(
                        () =>
                        {
                            this.ProjectSelector = null;
                        },
                        () =>
                        {
                            return true;
                        });

                }
                return this.cancelProjectSelectionCommand;
            }
            set
            {
                ICommand oldCommand = this.cancelProjectSelectionCommand;
                this.cancelProjectSelectionCommand = value as DelegatingCommand;
                if (oldCommand != this.cancelProjectSelectionCommand)
                    this.NotifyPropertyChanged("CancelProjectSelectionCommand");
            }
        }

        /// <summary>
        /// The command to invoke when the project selector is used to edit the async proxies destination projects
        /// </summary>
        public ICommand ConfirmAsyncProjectsSelectionCommand
        {
            get
            {
                if (this.confirmAsyncProjectsSelectionCommand == null)
                {
                    this.confirmAsyncProjectsSelectionCommand = new DelegatingCommand(
                        () =>
                        {
                            this.ProjectSelector = null;
                            List<string> stringList = this.SelectedAsyncProjects.Where(s => s.IsSelected).Select(s => s.ProjectName).ToList();
                            this.SelectedConfiguration.AsyncDestinationProjects = stringList;
                        },
                        () =>
                        {
                            return true;
                        });
                }
                return this.confirmAsyncProjectsSelectionCommand;
            }
        }

        /// <summary>
        /// The command to invoke when the project selector is used to edit the sync proxies destination projects
        /// </summary>
        public ICommand ConfirmSyncProjectsSelectionCommand
        {
            get
            {
                if (this.confirmSyncProjectsSelectionCommand == null)
                {
                    this.confirmSyncProjectsSelectionCommand = new DelegatingCommand(
                        () =>
                        {
                            this.ProjectSelector = null;
                            List<string> stringList = this.SelectedSyncProjects.Where(s => s.IsSelected).Select(s => s.ProjectName).ToList();
                            this.SelectedConfiguration.SyncDestinationProjects = stringList;
                        },
                        () =>
                        {
                            return true;
                        });
                }
                return this.confirmSyncProjectsSelectionCommand;
            }
        }

        public ICommand SelectGenerationFolderCommand
        {
            get
            {
                if (this.selectGenerationFolderCommand == null)
                {
                    this.selectGenerationFolderCommand = new DelegatingCommand(
                        () =>
                        {
                            System.Windows.Forms.FolderBrowserDialog browser = new System.Windows.Forms.FolderBrowserDialog();
                            browser.Description = AppResources.selectTempFolder;
                            if (this.SelectedConfiguration != null)
                            {
                                browser.SelectedPath = this.SelectedConfiguration.GenerationFolder;
                                if (browser.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                                {
                                    this.SelectedConfiguration.GenerationFolder = browser.SelectedPath;
                                }
                            }
                        },
                        () =>
                        {
                            return this.SelectedConfiguration != null;
                        }
                        );
                }
                return this.selectGenerationFolderCommand;
            }
        }


        public ICommand SelectTemplatesAssemblyCommand
        {
            get
            {
                if (this.selectTemplatesAssemblyCommand == null)
                {
                    this.selectTemplatesAssemblyCommand = new DelegatingCommand(
                        () =>
                        {
                            System.Windows.Forms.OpenFileDialog browser = new System.Windows.Forms.OpenFileDialog();
                            browser.Title = AppResources.selectTemplatesAssembly;
                            if (this.SelectedConfiguration != null)
                            {
                                browser.Multiselect = false;
                                browser.Filter = AppResources.templatesAssemblyFilter;
                                if (this.SelectedConfiguration.TemplatesAssemblyCodeBase != null)
                                {
                                    Uri uri = new Uri(this.SelectedConfiguration.TemplatesAssemblyCodeBase);
                                    browser.FileName = Path.GetFileName(uri.AbsolutePath);
                                    browser.InitialDirectory = Path.GetDirectoryName(uri.AbsolutePath);
                                }
                                if (browser.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                                {
                                    Uri uri = new Uri(browser.FileName);
                                    this.SelectedConfiguration.TemplatesAssemblyCodeBase = Uri.UnescapeDataString(uri.AbsoluteUri);
                                }
                            }
                        },
                        () =>
                        {
                            return this.SelectedConfiguration != null;
                        }
                        );
                }
                return this.selectTemplatesAssemblyCommand;
            }
        }

        public ICommand ToggleViewCommand
        {
            get
            {
                if (this.toggleViewCommand == null)
                {
                    this.toggleViewCommand = new DelegatingCommand(
                        () =>
                        {
                            this.IsAdvancedView = !this.IsAdvancedView;
                        },
                        () =>
                        {
                            return true;
                        });
                }
                return this.toggleViewCommand;
            }
        }

        public ICommand SelectTileImageCommand
        {
            get
            {
                if (this.selectTileImageCommand == null)
                {
                    this.selectTileImageCommand = new DelegatingCommand(
                        () =>
                        {
                            System.Windows.Forms.OpenFileDialog browser = new System.Windows.Forms.OpenFileDialog();
                            browser.Title = AppResources.selectTileImageFile;
                            if (this.SelectedConfiguration != null)
                            {
                                browser.Multiselect = false;
                                browser.Filter = AppResources.tileImageFileFilter;
                                if (this.SelectedConfiguration.TileImage != null)
                                {
                                    browser.FileName = this.SelectedConfiguration.TileImage;
                                    browser.InitialDirectory = Path.GetDirectoryName(this.SelectedConfiguration.TileImage);
                                }
                                if (browser.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                                {
                                    this.SelectedConfiguration.TileImage = browser.FileName;
                                }
                            }
                        },
                        () =>
                        {
                            return true;
                        });
                }
                return this.selectTileImageCommand;
            }
        }

        #endregion // Commands

        #endregion

        #region Instance Methods (Private)

        private void CreateSolutionProjectCollection()
        {
            ProjectInspector projectInspector = new ProjectInspector(this.applicationObject);
            this.solutionProjects = projectInspector.GetSolutionProjects();
        }

        private List<SelectedProject> CreateSelectedProjects(List<string> projectNames)
        {
            List<SelectedProject> selectedProjects = new List<SelectedProject>(this.SolutionProjects.Count);
            foreach (string project in this.SolutionProjects)
            {
                selectedProjects.Add(new SelectedProject { ProjectName = project, IsSelected = projectNames != null && projectNames.Contains(project) });
            }

            return selectedProjects;
        }

        private string GetNewClientConfigurationName()
        {
            int i = 1;
            while (this.clientConfigurations.FirstOrDefault(c => c.Name == string.Format("New Configuration {0}", i)) != null)
                i++;
            return string.Format("New Configuration {0}", i);
        }

        private void Close()
        {
            if (this.RequestClose != null)
            {
                this.RequestClose(this, EventArgs.Empty);
            }
        }

        private void AcceptConfigurationChanges()
        {
            if (this.SelectedConfiguration != null)
            {
                this.configuration.CurrentConfiguration = this.ClientConfigurations.IndexOf(this.SelectedConfiguration);
                this.configuration.ClientConfigurations = this.ClientConfigurations.ToList();
                if (this.ConfigurationChanged != null)
                {
                    this.ConfigurationChanged(this, new WcfClientGeneratorConfigEventArgs(this.configuration));
                }
            }
        }

        #endregion
    }
}
